Androidアプリで通知にボタンを追加して、タップ時にForeground Serviceを停止する
ユーザが任意のタイミングでForeground Serviceを終了したいとき、アプリを起動して操作するのは地味に手間です。 そこで、通知に「停止する」ボタンを表示して、そのボタンをタップしたらForeground Serviceを停止させてみました。
環境
- Android Studio 3.6
- Pixcel 3a (Android 10)
サンプルアプリを作ってみる
下記の続きから作成していきます。
ブロードキャストを受信するクラスを作成
通知の停止するボタンが選択されたことを受け取るブロードキャストレシーバーとして、LocationBroadcastReceiver.kt
を新規作成します。
onReceive()
でstopService()
を呼んでForeground Serviceを停止させます。
import android.content.BroadcastReceiver import android.content.Context import android.content.Intent class LocationBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val targetIntent = Intent(context, LocationService::class.java) context.stopService(targetIntent) } }
AndroidManifestファイルにブロードキャストレシーバークラスを追加
AndroidManifest.xml
にreceiver
を追加します。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="jp.test.tryforegroundservicesample"> ... <application ...> <activity android:name=".MainActivity"> ... </activity> <service android:name=".LocationService" /> <receiver android:name=".LocationBroadcastReceiver" android:exported="true"> <intent-filter> <action android:name="jp.test.tryforegroundservicesample.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> </application> </manifest>
- マニフェストで宣言されたレシーバー
- <action> | Android デベロッパー | Android Developers
- <category> | Android デベロッパー | Android Developers
- 暗黙的インテントを受け取る
通知表示に「停止する」ボタンを追加する
ForegroundServiceとして動くLocationService.kt
で作成している通知に「停止する」ボタンを追加します。
class LocationService : Service() { ... override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { ... val openIntent = Intent(this, MainActivity::class.java).let { PendingIntent.getActivity(this, 0, it, 0) } val sendIntent = Intent(this, LocationBroadcastReceiver::class.java).apply { action = ACTION_SEND } val sendPendingIntent = PendingIntent.getBroadcast(this, 0, sendIntent, 0) val notification = NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.ic_launcher_foreground) .setContentTitle("位置情報テスト") .setContentText("位置情報を取得しています...") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setContentIntent(openIntent) .addAction(R.drawable.ic_launcher_foreground, "停止する", sendPendingIntent) .build() startForeground(9999, notification) startLocationUpdates() return START_STICKY } }
動作確認
アプリをビルドして起動し、「START」ボタンを押すと、通知が表示されます。
ログもしっかり出力されています。
[1] 35.xxxx , 139.yyyy [2] 35.xxxx , 139.yyyy [3] 35.xxxx , 139.yyyy
この状態で通知にある「停止する」ボタンを押すと、通知が消えてログの出力も止まりました!
さいごに
Foreground Service実行時に表示される通知画面にボタンを追加し、そのボタンを選択するとForeground Serviceを終了させてみました。
BroadcastReceiver
なるものまで登場し、色々と絡み合っているんだなぁと思いつつ、BroadcastReceiver
についても分かりました。
どなたかの参考になれば幸いです。